/*
 * Copyright (c) 2015. For Intelligent Group.
 */

package com.intelligent.ispc.web.controller;

import com.intelligent.ispc.common.dto.JsonPageResponseDto;
import com.intelligent.ispc.common.dto.JsonResponseDto;
import com.intelligent.ispc.common.utils.ApplicationException;
import com.intelligent.ispc.common.utils.ExceptionMessages;
import com.intelligent.ispc.common.web.Servlets;
import com.intelligent.ispc.core.dto.RoleDto;
import com.intelligent.ispc.core.dto.SecurityUserDto;
import com.intelligent.ispc.core.dto.UserDto;
import com.intelligent.ispc.core.service.UserService;
import com.intelligent.ispc.utils.SystemConfig;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Peter.Li on 2015/10/8.
 */
@Controller
@RequestMapping(value = "/user")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private SystemConfig systemConfig;

    private Integer draw = 0;

    public PageRequest setPageObj(ServletRequest request) {
        Integer start = 0;
        if (StringUtils.isNotBlank(request.getParameter("start"))) {
            start = Integer.valueOf(request.getParameter("start"));
        }

        Integer size = systemConfig.getPageSize();
        if (StringUtils.isNotBlank(request.getParameter("length"))) {
            size = Integer.valueOf(request.getParameter("length"));
        }

        if (StringUtils.isNotBlank(request.getParameter("draw"))) {
            draw = Integer.valueOf(request.getParameter("draw"));
        }

        Integer pageNum = 0;
        if ((start / size) > 0) {
            pageNum = start / size;
        }
        return new PageRequest(pageNum, size);
    }

    @RequestMapping(value = "", method = RequestMethod.GET)
    public String nav(Model model, ServletRequest request) {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("system:user:view")) {
            return "error/noPermission";
        }
        return "user/userList";
    }

    @ResponseBody
    @RequestMapping(value = "/list")
    public JsonPageResponseDto list(Model model, ServletRequest request) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:view")) {
                return JsonPageResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            Map<String, Object> searchParam = Servlets.getParametersStartingWith(request, "search_");
            Page<UserDto> page = userService.searchUser(searchParam, setPageObj(request));
            List<UserDto> users1 = page.getContent();
            JsonPageResponseDto json = JsonPageResponseDto.SUCCESS().setBody(users1);
            json.setRecordsTotal(page.getTotalElements());
            json.setRecordsFiltered(page.getTotalElements());
            json.setDraw(draw);
            return json;
        } catch (Exception e) {
            return JsonPageResponseDto.FAILURE().setMessage(e.getMessage());
        }
    }

    @RequestMapping(value = "register", method = RequestMethod.GET)
    public String registerForm(Model model) {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("system:user:create")) {
            return "error/noPermission";
        }
        return "user/registerUser";
    }

    @ResponseBody
    @RequestMapping(value = "register", method = RequestMethod.POST)
    public JsonResponseDto register(UserDto user, String password, Model model) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:create")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            userService.saveUser(user, password);
            return JsonResponseDto.SUCCESS();
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
    }

    @RequestMapping(value = "edit/{id}", method = RequestMethod.GET)
    public String editForm(@PathVariable("id") String id, Model model) {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("system:user:edit")) {
            return "error/noPermission";
        }
        UserDto userDto = userService.findById(id);
        model.addAttribute("user", userDto);
        return "user/editUser";
    }

    @ResponseBody
    @RequestMapping(value = "update", method = RequestMethod.POST)
    public JsonResponseDto update(UserDto userDto, Model model) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:edit")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            userService.updateUser(userDto);
            return JsonResponseDto.SUCCESS();
        } catch (Exception e) {
            return JsonResponseDto.FAILURE().setMessage(e.getMessage());
        }
    }

    @ResponseBody
    @RequestMapping(value = "delete/{id}", method = RequestMethod.POST)
    public JsonResponseDto delete(@PathVariable("id") String id, Model models) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:delete")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            userService.deleteUser(id);
            return JsonResponseDto.SUCCESS();
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_SYSTEM);
        }
    }

    @ModelAttribute
    public void getUser(@RequestParam(value = "id", defaultValue = "") String id, Model model) {
        try {
            if (StringUtils.isNotBlank(id)) {
                model.addAttribute("user", userService.findById(id));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @ResponseBody
    @RequestMapping(value = "assignRole", method = RequestMethod.POST)
    public JsonResponseDto assignRole(Model model, @RequestParam("userId") String userId, @RequestParam("roleId") List<String> roleIds) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:edit")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            userService.assignRolesForUser(userId, roleIds);
            return JsonResponseDto.SUCCESS();
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
    }

    @ResponseBody
    @RequestMapping(value = "deleteRole", method = RequestMethod.POST)
    public JsonResponseDto deleteRolesForUser(Model model, @RequestParam("userId") String userId, @RequestParam("roleId") List<String> roleIds) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:edit")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            userService.deleteRolesForUser(userId, roleIds);
            return JsonResponseDto.SUCCESS();
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
    }

    @ResponseBody
    @RequestMapping(value = "findUserCanAddRoles/{id}", method = RequestMethod.POST)
    public JsonResponseDto findUserCanAddRoles(Model model, @PathVariable("id") String userId) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:view")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }

            List<RoleDto> UserCanAddRoles = userService.findUserCanAddRoles(userId);
            List<RoleDto> userHaveRoleDtos = userService.findUserHaveRole(userId);
            Map<String, Object> userRoleMap = new HashMap<String, Object>();
            userRoleMap.put("findUserCanAddRoles", UserCanAddRoles);
            userRoleMap.put("userHaveRoleDtos", userHaveRoleDtos);

            return JsonResponseDto.SUCCESS().setBody(userRoleMap);
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_SYSTEM);
        }
    }

    @ResponseBody
    @RequestMapping(value = "findUserHaveRole/{id}", method = RequestMethod.POST)
    public JsonResponseDto findUserHaveRole(Model model, @PathVariable("id") String userId) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:view")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            List<RoleDto> roleDtos = userService.findUserHaveRole(userId);
            return JsonResponseDto.SUCCESS().setBody(roleDtos);
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
    }

    @ResponseBody
    @RequestMapping(value = "resetPassword/{id}", method = RequestMethod.POST)
    public JsonResponseDto resetPassword(Model model, @PathVariable("id") String userId) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:edit")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            userService.resetPassword(userId);
            return JsonResponseDto.SUCCESS();
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
    }


    @RequestMapping(value = "profile", method = RequestMethod.GET)
    public String profile(Model model) {
        Subject subject = SecurityUtils.getSubject();
        if (!subject.isPermitted("system:user:view")) {
            return "error/noPermission";
        }
        SecurityUserDto securityUserDto = (SecurityUserDto) subject.getPrincipal();
        UserDto userDto = userService.findById(securityUserDto.getId().toString());
        model.addAttribute("user", userDto);
        model.addAttribute("roles", userDto.getRoles());
        return "user/profile";
    }

    @ResponseBody
    @RequestMapping(value = "/updatePassword", method = RequestMethod.POST)
    public JsonResponseDto updatePassword(UserDto userDto, String password, String newPassword, Model model) {
        try {
            Subject subject = SecurityUtils.getSubject();
            if (!subject.isPermitted("system:user:edit")) {
                return JsonResponseDto.FAILURE().setMessage(ExceptionMessages.EXCEPTION_NO_PERMISSION);
            }
            userService.updatePassword(userDto.getLoginName(), password, newPassword);
            return JsonResponseDto.SUCCESS();
        } catch (ApplicationException ex) {
            return JsonResponseDto.FAILURE().setMessage(ex.getMessage());
        }
    }
}
